using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace DA.AnimGraph.Editor {

    public class PaneSplitter : VisualElement {

        public enum Direction {
            Row, // 横
            Column, // 纵
        }

        /// <param name="sign">控制右、下填-1，左、上填1</param>
        public PaneSplitter(VisualElement target, Direction direction, int sign) {
            if (direction == Direction.Row) {
                style.cursor = AGEStyleUtility.LoadCursor(MouseCursor.SplitResizeLeftRight);
                style.width = 4;
                style.height = Length.Percent(100);
                this.AddManipulator(new SplitterManipulator(target, FlexDirection.Row, sign));
            } else {
                style.cursor = AGEStyleUtility.LoadCursor(MouseCursor.SplitResizeUpDown);
                style.height = 4;
                style.width = Length.Percent(100);
                this.AddManipulator(new SplitterManipulator(target, FlexDirection.Column, sign));
            }
            style.backgroundColor = Color.gray;
        }


    }

    public class SplitterManipulator : MouseManipulator {
        private readonly VisualElement targetElement;
        private readonly FlexDirection flexDir;
        private readonly int sign;
        private bool isActive;
        private Vector2 start;
        private float oldSize;


        public SplitterManipulator(VisualElement targetElement, FlexDirection flexDir, int sign) {
            this.targetElement = targetElement;
            this.flexDir = flexDir;
            this.sign = sign;

            activators.Add(new ManipulatorActivationFilter {
                button = MouseButton.LeftMouse,
            });
        }

        public void ApplyDelta(float delta) {
            var newSize = oldSize + delta;
            if (flexDir == FlexDirection.Row) {
                targetElement.style.width = newSize;
            } else {
                targetElement.style.height = newSize;
            }
        }


        protected override void RegisterCallbacksOnTarget() {
            target.RegisterCallback<MouseDownEvent>(OnMouseDown);
            target.RegisterCallback<MouseMoveEvent>(OnMouseMove);
            target.RegisterCallback<MouseUpEvent>(OnMouseUp);
        }

        protected override void UnregisterCallbacksFromTarget() {
            target.UnregisterCallback<MouseDownEvent>(OnMouseDown);
            target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);
            target.UnregisterCallback<MouseUpEvent>(OnMouseUp);
        }


        private void OnMouseDown(MouseDownEvent e) {
            if (isActive) {
                e.StopImmediatePropagation();
                return;
            }

            if (CanStartManipulation(e)) {
                isActive = true;
                start = e.mousePosition;
                oldSize = flexDir == FlexDirection.Row
                    ? targetElement.resolvedStyle.width
                    : targetElement.resolvedStyle.height;

                target.CaptureMouse();

                e.StopPropagation();
            }
        }

        private void OnMouseMove(MouseMoveEvent e) {
            if (!isActive || !target.HasMouseCapture()) {
                return;
            }

            Vector2 mouseDelta = e.mousePosition - start;
            float sizeDelta = (flexDir == FlexDirection.Row ? mouseDelta.x : mouseDelta.y) * sign;
            ApplyDelta(sizeDelta);

            e.StopPropagation();
        }

        private void OnMouseUp(MouseUpEvent e) {
            if (!isActive || !target.HasMouseCapture() || !CanStopManipulation(e)) {
                return;
            }

            isActive = false;

            target.ReleaseMouse();

            e.StopPropagation();
        }
    }
}
